#include <p18f2455.h>
#include "configs.h"
#include "usb_defs.h"
#include <delays.h>
//#define	SHOW_ENUM_STATUS

#include <spi.h>					// Microchip SPI library file - makes all this possible!
#include "h_SPI_Example_Code.h"		// Header file (has function prototypes, etc.)
// Specific to PIC18f2455 Configuration (change the pins based on your PIC type/data sheet)
// Define names for the various SPI pins. 
#define SDO 		PORTCbits.RC7			// Serial Data Out (SDO)	-- Pin that data goes out from	(common to all devices)
#define SDI 		PORTBbits.RB0			// Serial Data In (SDI)		-- Pin that data comes in to	(common to all devices)
#define SDI_DIR 	TRISBbits.TRISB0		// Direction of SDI signal  -- You want to be able to set it as an "input" since you're 
#define SCK 		PORTBbits.RB1			// Serial Clock (SCK)		-- Pin that sends a clock signal that synchronizes all  SPI devices	(common to all devices)
#define RESET		PORTBbits.RB7			// Reset					-- Pin that resets the GPIO chip
#define RESET_DIR	TRISBbits.TRISB7			// Direction of reset signal-- You want to set it as "output"


#define IODIRA	 0x00
#define IODIRB	 0x01
#define IOCON	 0x0A
#define GPIOA	 0x12
#define GPIOB	 0x13
#define OLATA	 0X14

// Here, you define your various "Slave Select" pins. These can be whatever general I/O pin you'd like
#define SS  		PORTBbits.RB4			// Slave Select (SS)		-- Pin that selects which "slave" module you are communicating with
#define ADSS		PORTCbits.RC6			// AD chip select


#define select 		0						// Since most devices are "active low", define "select" as 0
#define deselect	1
unsigned char chip1 = 1;
unsigned char chip2	= 2;


#define	SET_SERVO		0x01		// vendor-specific request to set (i.e., make high) RA4
#define KILL_CREEPA		0x02		// vendor request to kill creep at positions 0 - 7
#define	TOWERTIMEARRAY	0x03		// vendor request to get tower positions
#define KILL_CREEPB		0x04		// vendor request to kill creep at positions 0 - 7
#define	GET_RA0			0x05		// vendor-specific request to read RA2
#define FIRING			0x06		// vendor-specific request to set the duty cycle of the blinking LED on RA0
#define GET_TOWERTYPE   0x07
#define GET_TOWERPOS    0x08
#define GET_TICK		0x09
#define UNKILL_CREEPA	0X0A
#define UNKILL_CREEPB	0x0B

#pragma udata
BUFDESC USB_buffer_desc;
unsigned char USB_buffer_data[8];
unsigned char USB_error_flags;
unsigned char USB_curr_config;
unsigned char USB_device_status;
unsigned char USB_dev_req;
unsigned char USB_address_pending;
unsigned char rom *USB_desc_ptr;
unsigned char USB_bytes_left;
unsigned char USB_packet_length;
unsigned char USB_USTAT;
unsigned char USB_USWSTAT;


unsigned char SERVO_PLACEMENT=0b10000000;
unsigned char tower;
unsigned char spi_tower;
unsigned char killtower;
unsigned char killvalueA = 0x00;
unsigned char killvalueB = 0x00;
unsigned char towertimearray[8] = {0,0,0,0,0,0,0,0};
unsigned char delay_array;
unsigned char AD_data;
unsigned char AD_array[8] = {0,0,0,0,0,0,0,0};
unsigned char AD_type_array[8] = {0,0,0,0,0,0,0,0};
unsigned char channel;
unsigned char pollbyte;
unsigned char i;
unsigned char adport;
unsigned char firing;
unsigned char CREEP_VALUE = 0x00;
unsigned char creep_checkin;
unsigned char checkfortowers;
unsigned char towerchange;
unsigned char tower_type[8] = {0,0,0,0,0,0,0,0};
unsigned char towerpos;
unsigned char tower_change;
unsigned char towertypearray[8] = {0,0,0,0,0,0,0,0};
unsigned char tick_checkin;

signed long chargecycle=0;
signed deltacharge=10;

#pragma romdata
rom const unsigned char Device[] = {
	0x12,	// bLength
	DEVICE,	// bDescriptorType
	0x10,	// bcdUSB (low byte)
	0x01,	// bcdUSB (high byte)
	0x00,	// bDeviceClass
	0x00,	// bDeviceSubClass
	0x00,	// bDeviceProtocol
	MAX_PACKET_SIZE,	// bMaxPacketSize
	0x66,	// idVendor (low byte)
	0x66,	// idVendor (high byte)
	0x03,	// idProduct (low byte)
	0x00,	// idProduct (high byte)
	0x00,	// bcdDevice (low byte)
	0x00,	// bcdDevice (high byte)
	0x01,	// iManufacturer
	0x02,	// iProduct
	0x00,	// iSerialNumber (none)
	NUM_CONFIGURATIONS	// bNumConfigurations
};

rom const unsigned char Configuration1[] = {
	0x09,	// bLength
	CONFIGURATION,	// bDescriptorType
	0x12,	// wTotalLength (low byte)
	0x00,	// wTotalLength (high byte)
	NUM_INTERFACES,	// bNumInterfaces
	0x01,	// bConfigurationValue
	0x00,	// iConfiguration (none)
	0xA0,	// bmAttributes
	0x32,	// bMaxPower (100 mA)
	0x09,	// bLength (Interface1 descriptor starts here)
	INTERFACE,	// bDescriptorType
	0x00,	// bInterfaceNumber
	0x00,	// bAlternateSetting
	0x00,	// bNumEndpoints (excluding EP0)
	0xFF,	// bInterfaceClass (vendor specific class code)
	0x00,	// bInterfaceSubClass
	0xFF,	// bInterfaceProtocol (vendor specific protocol used)
	0x00	// iInterface (none)
};

rom const unsigned char String0[] = {
	0x04,	// bLength
	STRING,	// bDescriptorType
	0x09,	// wLANGID[0] (low byte)
	0x04	// wLANGID[0] (high byte)
};

rom const unsigned char String1[] = {
	0x34,	// bLength
	STRING,	// bDescriptorType
	'P', 0x00, 'r', 0x00, 'i', 0x00, 'n', 0x00, 'c', 0x00, 'i', 0x00, 'p', 0x00, 'l', 0x00, 'e', 0x00, 's', 0x00, ' ', 0x00,
	'o', 0x00, 'f', 0x00, ' ', 0x00,
	'E', 0x00, 'n', 0x00, 'g', 0x00, 'i', 0x00, 'n', 0x00, 'e', 0x00, 'e', 0x00, 'r', 0x00, 'i', 0x00, 'n', 0x00, 'g', 0x00
};

rom const unsigned char String2[] = {
	0x32,	// bLength
	STRING,	// bDescriptorType
	'E', 0x00, 'N', 0x00, 'G', 0x00, 'R', 0x00, ' ', 0x00, '2', 0x00, '2', 0x00, '1', 0x00, '0', 0x00, ' ', 0x00,
	'L', 0x00, 'a', 0x00, 'b', 0x00, ' ', 0x00, '3', 0x00, ' ', 0x00, 
	'F', 0x00, 'i', 0x00, 'r', 0x00, 'm', 0x00, 'w', 0x00, 'a', 0x00, 'r', 0x00, 'e', 0x00
};

#pragma code
void InitUSB(void) {
	UIE = 0x00;					// mask all USB interrupts
	UIR = 0x00;					// clear all USB interrupt flags
	UCFG = 0x10;				// configure USB for low-speed transfers and to use the on-chip transciever and pull-up resistor
	UCON = 0x08;				// enable the USB module and its supporting circuitry
	USB_curr_config = 0x00;
	USB_USWSTAT = 0x00;			// default to powered state
	USB_device_status = 0x01;
	USB_dev_req = NO_REQUEST;	// No device requests in process
#ifdef SHOW_ENUM_STATUS
	TRISB = 0x00;				// set all bits of PORTB as outputs
	PORTB = 0x01;				// set bit zero to indicate Powered status
#endif
	while (UCONbits.SE0);		// wait for the first SE0 to end
}

void ServiceUSB(void) {
	BUFDESC *buf_desc_ptr;

	if (UIRbits.UERRIF) {
		UEIR = 0x00;
	} else if (UIRbits.SOFIF) {
		UIRbits.SOFIF = 0;
	} else if (UIRbits.IDLEIF) {
		UIRbits.IDLEIF = 0;
		UCONbits.SUSPND = 1;
#ifdef SHOW_ENUM_STATUS
		PORTB &= 0xE0;
		PORTBbits.RB4 = 1;
#endif
	} else if (UIRbits.ACTVIF) {
		UIRbits.ACTVIF = 0;
		UCONbits.SUSPND = 0;
#ifdef SHOW_ENUM_STATUS
		PORTB &= 0xE0;
		PORTB |= 0x01<<USB_USWSTAT;
#endif
	} else if (UIRbits.STALLIF) {
		UIRbits.STALLIF = 0;
	} else if (UIRbits.URSTIF) {
		USB_curr_config = 0x00;
		UIRbits.TRNIF = 0;		// clear TRNIF four times to clear out the USTAT FIFO
		UIRbits.TRNIF = 0;
		UIRbits.TRNIF = 0;
		UIRbits.TRNIF = 0;
		UEP0 = 0x00;				// clear all EP control registers to disable all endpoints
		UEP1 = 0x00;
		UEP2 = 0x00;
		UEP3 = 0x00;
		UEP4 = 0x00;
		UEP5 = 0x00;
		UEP6 = 0x00;
		UEP7 = 0x00;
		UEP8 = 0x00;
		UEP9 = 0x00;
		UEP10 = 0x00;
		UEP11 = 0x00;
		UEP12 = 0x00;
		UEP13 = 0x00;
		UEP14 = 0x00;
		UEP15 = 0x00;
		BD0O.bytecount = MAX_PACKET_SIZE;
		BD0O.address = EP0_OUT_buffer;	// EP0 OUT gets a buffer
		BD0O.status = 0x88;				// set UOWN bit (USB can write)
		BD0I.address = EP0_IN_buffer;	// EP0 IN gets a buffer
		BD0I.status = 0x08;				// clear UOWN bit (MCU can write)
		UADDR = 0x00;				// set USB Address to 0
		UIR = 0x00;				// clear all the USB interrupt flags
		UEP0 = ENDPT_CONTROL;	// EP0 is a control pipe and requires an ACK
		UEIE = 0xFF;			// enable all error interrupts
		USB_USWSTAT = DEFAULT_STATE;
		USB_device_status = 0x01;	// self powered, remote wakeup disabled
/*#ifdef SHOW_ENUM_STATUS
		PORTB &= 0xE0;
		PORTBbits.RB1 = 1;		// set bit 1 of PORTB to indicate Powered state
#endif*/
	} else if (UIRbits.TRNIF) {
		buf_desc_ptr = (BUFDESC *)((unsigned char *)(&BD0O)+(USTAT&0x7C));	// mask out bits 0, 1, and 7 of USTAT for offset into the buffer descriptor table
		USB_buffer_desc.status = buf_desc_ptr->status;
		USB_buffer_desc.bytecount = buf_desc_ptr->bytecount;
		USB_buffer_desc.address = buf_desc_ptr->address;
		USB_USTAT = USTAT;		// save the USB status register
		UIRbits.TRNIF = 0;		// clear TRNIF interrupt flag
#ifdef SHOW_ENUM_STATUS
		switch (USB_USTAT&0x18) {	// toggle bit 5, 6, or 7 of PORTB to reflect EP0, EP1, or EP2 activity
			case EP0:
				PORTB ^= 0x20;
				break;
			case EP1:
				PORTB ^= 0x40;
				break;
			case EP2:
				PORTB ^= 0x80;
		}
#endif
		USB_error_flags = 0x00;	// clear USB error flags
		switch (USB_buffer_desc.status&0x3C) {	// extract PID bits
			case TOKEN_SETUP:
				ProcessSetupToken();
				break;
			case TOKEN_IN:
				ProcessInToken();
				break;
			case TOKEN_OUT:
				ProcessOutToken();
		}
		if (USB_error_flags&0x01) {		// if there was a Request Error...
			BD0O.bytecount = MAX_PACKET_SIZE;	// ...get ready to receive the next Setup token...
			BD0I.status = 0x84;
			BD0O.status = 0x84;					// ...and issue a protocol stall on EP0
		}
	}
}

void ProcessSetupToken(void) {
	unsigned char n;

	for (n = 0; n<8; n++) {
		USB_buffer_data[n] = USB_buffer_desc.address[n];
	}
	BD0O.bytecount = MAX_PACKET_SIZE;	// reset the EP0 OUT byte count
	BD0I.status = 0x08;			// return the EP0 IN buffer to us (dequeue any pending requests)			
	BD0O.status = (!(USB_buffer_data[bmRequestType]&0x80) && (USB_buffer_data[wLength] || USB_buffer_data[wLengthHigh])) ? 0xC8:0x88;	// set EP0 OUT UOWN back to USB and DATA0/DATA1 packet according to the request type
	UCONbits.PKTDIS = 0;			// assuming there is nothing to dequeue, clear the packet disable bit
	USB_dev_req = NO_REQUEST;		// clear the device request in process
	switch (USB_buffer_data[bmRequestType]&0x60) {	// extract request type bits
		case STANDARD:
			StandardRequests();
			break;
		case CLASS:
			ClassRequests();
			break;
		case VENDOR:
			VendorRequests();
			break;
		default:
			USB_error_flags |= 0x01;	// set Request Error Flag
	}
}

void StandardRequests(void) {
	unsigned char *UEP;
	unsigned char n;
	BUFDESC *buf_desc_ptr;

	switch (USB_buffer_data[bRequest]) {
		case GET_STATUS:
			switch (USB_buffer_data[bmRequestType]&0x1F) {	// extract request recipient bits
				case RECIPIENT_DEVICE:
					BD0I.address[0] = USB_device_status;
					BD0I.address[1] = 0x00;
					BD0I.bytecount = 0x02;
					BD0I.status = 0xC8;		// send packet as DATA1, set UOWN bit
					break;
				case RECIPIENT_INTERFACE:
					switch (USB_USWSTAT) {
						case ADDRESS_STATE:
							USB_error_flags |= 0x01;	// set Request Error Flag
							break;
						case CONFIG_STATE:
							if (USB_buffer_data[wIndex]<NUM_INTERFACES) {
								BD0I.address[0] = 0x00;
								BD0I.address[1] = 0x00;
								BD0I.bytecount = 0x02;
								BD0I.status = 0xC8;		// send packet as DATA1, set UOWN bit
							} else {
								USB_error_flags |= 0x01;	// set Request Error Flag
							}
					}
					break;
				case RECIPIENT_ENDPOINT:
					switch (USB_USWSTAT) {
						case ADDRESS_STATE:
							if (!(USB_buffer_data[wIndex]&0x0F)) {	// get EP, strip off direction bit and see if it is EP0
								BD0I.address[0] = (((USB_buffer_data[wIndex]&0x80) ? BD0I.status:BD0O.status)&0x04)>>2;	// return the BSTALL bit of EP0 IN or OUT, whichever was requested
								BD0I.address[1] = 0x00;
								BD0I.bytecount = 0x02;
								BD0I.status = 0xC8;		// send packet as DATA1, set UOWN bit
							} else {
								USB_error_flags |= 0x01;	// set Request Error Flag
							}
							break;
						case CONFIG_STATE:
							UEP = (unsigned char *)&UEP0;
							n = USB_buffer_data[wIndex]&0x0F;	// get EP and strip off direction bit for offset from UEP0
							buf_desc_ptr = &BD0O+((n<<1)|((USB_buffer_data[wIndex]&0x80) ? 0x01:0x00));	// compute pointer to the buffer descriptor for the specified EP
							if (UEP[n]&((USB_buffer_data[wIndex]&0x80) ? 0x02:0x04)) { // if the specified EP is enabled for transfers in the specified direction...
								BD0I.address[0] = ((buf_desc_ptr->status)&0x04)>>2;	// ...return the BSTALL bit of the specified EP
								BD0I.address[1] = 0x00;
								BD0I.bytecount = 0x02;
								BD0I.status = 0xC8;		// send packet as DATA1, set UOWN bit
							} else {
								USB_error_flags |= 0x01;	// set Request Error Flag
							}
							break;
						default:
							USB_error_flags |= 0x01;	// set Request Error Flag
					}
					break;
				default:
					USB_error_flags |= 0x01;	// set Request Error Flag
			}
			break;
		case CLEAR_FEATURE:
		case SET_FEATURE:
			switch (USB_buffer_data[bmRequestType]&0x1F) {	// extract request recipient bits
				case RECIPIENT_DEVICE:
					switch (USB_buffer_data[wValue]) {
						case DEVICE_REMOTE_WAKEUP:
							if (USB_buffer_data[bRequest]==CLEAR_FEATURE)
								USB_device_status &= 0xFE;
							else
								USB_device_status |= 0x01;
							BD0I.bytecount = 0x00;		// set EP0 IN byte count to 0
							BD0I.status = 0xC8;		// send packet as DATA1, set UOWN bit
							break;
						default:
							USB_error_flags |= 0x01;	// set Request Error Flag
					}
					break;
				case RECIPIENT_ENDPOINT:
					switch (USB_USWSTAT) {
						case ADDRESS_STATE:
							if (!(USB_buffer_data[wIndex]&0x0F)) {	// get EP, strip off direction bit, and see if its EP0
								BD0I.bytecount = 0x00;		// set EP0 IN byte count to 0
								BD0I.status = 0xC8;		// send packet as DATA1, set UOWN bit
							} else {
								USB_error_flags |= 0x01;	// set Request Error Flag
							}
							break;
						case CONFIG_STATE:
							UEP = (unsigned char *)&UEP0;
							if (n = USB_buffer_data[wIndex]&0x0F) {	// get EP and strip off direction bit for offset from UEP0, if not EP0...
								buf_desc_ptr = &BD0O+((n<<1)|((USB_buffer_data[wIndex]&0x80) ? 0x01:0x00));	// compute pointer to the buffer descriptor for the specified EP
								if (USB_buffer_data[wIndex]&0x80) {	// if the specified EP direction is IN...
									if (UEP[n]&0x02) {	// if EPn is enabled for IN transfers...
										buf_desc_ptr->status = (USB_buffer_data[bRequest]==CLEAR_FEATURE) ? 0x00:0x84;
									} else {
										USB_error_flags |= 0x01;	// set Request Error Flag									
									}
								} else {	// ...otherwise the specified EP direction is OUT, so...
									if (UEP[n]&0x04) {	// if EPn is enabled for OUT transfers...
										buf_desc_ptr->status = (USB_buffer_data[bRequest]==CLEAR_FEATURE) ? 0x88:0x84;
									} else {
										USB_error_flags |= 0x01;	// set Request Error Flag									
									}
								}
							}
							if (!(USB_error_flags&0x01)) {	// if there was no Request Error...
								BD0I.bytecount = 0x00;
								BD0I.status = 0xC8;		// ...send packet as DATA1, set UOWN bit
							}
							break;
						default:
							USB_error_flags |= 0x01;	// set Request Error Flag
					}
					break;
				default:
					USB_error_flags |= 0x01;	// set Request Error Flag
			}
			break;
		case SET_ADDRESS:
			if (USB_buffer_data[wValue]>0x7F) {	// if new device address is illegal, send Request Error
				USB_error_flags |= 0x01;	// set Request Error Flag
			} else {
				USB_dev_req = SET_ADDRESS;	// processing a SET_ADDRESS request
				USB_address_pending = USB_buffer_data[wValue];	// save new address
				BD0I.bytecount = 0x00;		// set EP0 IN byte count to 0
				BD0I.status = 0xC8;		// send packet as DATA1, set UOWN bit
			}
			break;
		case GET_DESCRIPTOR:
			USB_dev_req = GET_DESCRIPTOR;	// processing a GET_DESCRIPTOR request
			switch (USB_buffer_data[wValueHigh]) {
				case DEVICE:
					USB_desc_ptr = Device;
					USB_bytes_left = USB_desc_ptr[0];
					if ((USB_buffer_data[wLengthHigh]==0x00) && (USB_buffer_data[wLength]<USB_bytes_left)) {
						USB_bytes_left = USB_buffer_data[wLength];
					}
					SendDescriptorPacket();
					break;
				case CONFIGURATION:
					switch (USB_buffer_data[wValue]) {
						case 0:
							USB_desc_ptr = Configuration1;
							break;
						default:
							USB_error_flags |= 0x01;	// set Request Error Flag
					}
					if (!(USB_error_flags&0x01)) {
						USB_bytes_left = USB_desc_ptr[2];	// wTotalLength at an offset of 2
						if ((USB_buffer_data[wLengthHigh]==0x00) && (USB_buffer_data[wLength]<USB_bytes_left)) {
							USB_bytes_left = USB_buffer_data[wLength];
						}
						SendDescriptorPacket();
					}
					break;
				case STRING:
					switch (USB_buffer_data[wValue]) {
						case 0:
							USB_desc_ptr = String0;
							break;
						case 1:
							USB_desc_ptr = String1;
							break;
						case 2:
							USB_desc_ptr = String2;
							break;
						default:
							USB_error_flags |= 0x01;	// set Request Error Flag
					}
					if (!(USB_error_flags&0x01)) {
						USB_bytes_left = USB_desc_ptr[0];
						if ((USB_buffer_data[wLengthHigh]==0x00) && (USB_buffer_data[wLength]<USB_bytes_left)) {
							USB_bytes_left = USB_buffer_data[wLength];
						}
						SendDescriptorPacket();
					}
					break;
				default:
					USB_error_flags |= 0x01;	// set Request Error Flag
			}
			break;
		case GET_CONFIGURATION:
			BD0I.address[0] = USB_curr_config;	// copy current device configuration to EP0 IN buffer
			BD0I.bytecount = 0x01;
			BD0I.status = 0xC8;		// send packet as DATA1, set UOWN bit
			break;
		case SET_CONFIGURATION:
			if (USB_buffer_data[wValue]<=NUM_CONFIGURATIONS) {
				UEP1 = 0x00;	// clear all EP control registers except for EP0 to disable EP1-EP15 prior to setting configuration
				UEP2 = 0x00;
				UEP3 = 0x00;
				UEP4 = 0x00;
				UEP5 = 0x00;
				UEP6 = 0x00;
				UEP7 = 0x00;
				UEP8 = 0x00;
				UEP9 = 0x00;
				UEP10 = 0x00;
				UEP11 = 0x00;
				UEP12 = 0x00;
				UEP13 = 0x00;
				UEP14 = 0x00;
				UEP15 = 0x00;
				switch (USB_curr_config = USB_buffer_data[wValue]) {
					case 0:
						USB_USWSTAT = ADDRESS_STATE;
/*#ifdef SHOW_ENUM_STATUS
						PORTB &= 0xE0;
						PORTBbits.RB2 = 1;
#endif
*/
						break;
					default:
						USB_USWSTAT = CONFIG_STATE;
/*#ifdef SHOW_ENUM_STATUS
						PORTB &= 0xE0;
						PORTBbits.RB3 = 1;
#endif
*/
				}
				BD0I.bytecount = 0x00;		// set EP0 IN byte count to 0
				BD0I.status = 0xC8;		// send packet as DATA1, set UOWN bit
			} else {
				USB_error_flags |= 0x01;	// set Request Error Flag
			}
			break;
		case GET_INTERFACE:
			switch (USB_USWSTAT) {
				case CONFIG_STATE:
					if (USB_buffer_data[wIndex]<NUM_INTERFACES) {
						BD0I.address[0] = 0x00;	// always send back 0 for bAlternateSetting
						BD0I.bytecount = 0x01;
						BD0I.status = 0xC8;		// send packet as DATA1, set UOWN bit
					} else {
						USB_error_flags |= 0x01;	// set Request Error Flag
					}
					break;
				default:
					USB_error_flags |= 0x01;	// set Request Error Flag
			}
			break;
		case SET_INTERFACE:
			switch (USB_USWSTAT) {
				case CONFIG_STATE:
					if (USB_buffer_data[wIndex]<NUM_INTERFACES) {
						switch (USB_buffer_data[wValue]) {
							case 0:		// currently support only bAlternateSetting of 0
								BD0I.bytecount = 0x00;		// set EP0 IN byte count to 0
								BD0I.status = 0xC8;		// send packet as DATA1, set UOWN bit
								break;
							default:
								USB_error_flags |= 0x01;	// set Request Error Flag
						}
					} else {
						USB_error_flags |= 0x01;	// set Request Error Flag
					}
					break;
				default:
					USB_error_flags |= 0x01;	// set Request Error Flag
			}
			break;
		case SET_DESCRIPTOR:
		case SYNCH_FRAME:
		default:
			USB_error_flags |= 0x01;	// set Request Error Flag
	}
}

void ClassRequests(void) {
	switch (USB_buffer_data[bRequest]) {
		default:
			USB_error_flags |= 0x01;	// set Request Error Flag
	}
}

// Writes a value to the SPI
void WriteSomething(unsigned char chip, unsigned char address, unsigned char val)
{
	INTCONbits.GIE = 0;				// Disable Global Interrupts (so an interrupt doesn't mess up your SPI communication)
	if (chip == 1){
	PORTBbits.RB4 = select;					// Select Device
	putcSPI(0x40);
	putcSPI(address);					// 000100115
	putcSPI(val);					// Writes one byte to the spi
	PORTBbits.RB4 = deselect;				

	}else if (chip == 2){
	PORTBbits.RB5 = select;					// Select Device
	putcSPI(0x40);
	putcSPI(address);					// 000100115
	putcSPI(val);					// Writes one byte to the spi
	PORTBbits.RB5 = deselect;					// Deselect Device
	}
	INTCONbits.GIE = 1;				// Enable interrupts again
}


void RequestAByte(unsigned char read_request)
{
	ADSS = select;					// Select Device
	putcSPI(read_request); 			//send the ADC a request (0b1xxx1111) to read us a value. When it receives this cmd, wil lsend us a val
	getcSPI(); 						//read data byte. [keeps reading until gets an entire byte of data].
	AD_data = SSPBUF;
	ADSS = deselect;					// Deselect Device	

}

// Initializes an SPI connection
void InitSPI() 
{	
	SDI		= 0;					// Just in case, reset SDI pin value
	SDI_DIR = 1;					// Set serialIn High (pull not_CS high.)
	RESET_DIR = 0;					// Reset pin is an output
	RESET = 0;
	Delay10KTCYx(10); // reset for 10*10K cycles
	RESET = 1;

	OpenSPI(SPI_FOSC_4, MODE_00, SMPEND);	//Open a SPI module (Code within spi.h)

	WriteSomething(chip1, IOCON, 0x28);		//Bank is 0 (register addresses are right) Bit Mode (Sequential mode disabled), HAEN is on
	WriteSomething(chip1, IODIRA, 0x00);	
	WriteSomething(chip1, IODIRB, 0x00);
	WriteSomething(chip1, GPIOA, 0x00);
	WriteSomething(chip1, GPIOB, 0x00);

	WriteSomething(chip2, IOCON, 0x28);
	WriteSomething(chip2, IODIRA, 0x00);
	WriteSomething(chip2, IODIRB, 0x00);
	WriteSomething(chip2, GPIOA, 0x00);
	WriteSomething(chip2, GPIOB, 0x00);
	
}

void VendorRequests(void) {
/*	if (service_servos == 1) {
		
	service_servos_counter++;
	}*/
	switch (USB_buffer_data[bRequest]) {
		case SET_SERVO:
		SERVO_PLACEMENT= USB_buffer_data[wValue];
		SERVO_PLACEMENT = 135-( ( float )SERVO_PLACEMENT * 110) / 255.0;
		BD0I.bytecount = 0x00;
		BD0I.status = 0xC8;
		break;
		
		case KILL_CREEPA:
		killtower= USB_buffer_data[wValue];
		killvalueA = killvalueA ^ (0x01<<killtower);
		BD0I.bytecount = 0x00;
		BD0I.status = 0xC8;
		break;

		case KILL_CREEPB:
		killtower= USB_buffer_data[wValue];
		killvalueB = killvalueB ^ (0x1<<killtower);
		BD0I.bytecount = 0x00;
		BD0I.status = 0xC8;
		break;
		

		case TOWERTIMEARRAY:
		USB_dev_req = TOWERTIMEARRAY;
        delay_array = USB_buffer_data[wIndex];
		USB_packet_length = USB_buffer_data[wLength];
		break;

		case GET_RA0:
		BD0I.address[0] = (creep_checkin) ? 0x01:0x00;	// if creep_checkin is high, put 0x01 into EP0 IN buffer, else put 0x00 into EP0 IN buffer
		BD0I.bytecount = 0x01;		// set EP0 IN byte count to 1
		BD0I.status = 0xC8;			// send packet as DATA1, set UOWN bit
			break;

		case FIRING:
		firing = USB_buffer_data[wValue];
		BD0I.bytecount = 0x00;
		BD0I.status = 0xC8;
		break;

		case GET_TOWERTYPE:
		for (tower = 0; tower < 8; tower++){
		BD0I.address[0] = (tower_type[tower]) ? 0x01:0x00;
		}							// if creep_checkin is high, put 0x01 into EP0 IN buffer, else put 0x00 into EP0 IN buffer
		BD0I.bytecount = 0x01;		// set EP0 IN byte count to 1
		BD0I.status = 0xC8;			// send packet as DATA1, set UOWN bit
		break;

		case GET_TOWERPOS:
		BD0I.address[0] = towerpos;
		BD0I.bytecount = 0x01;		// set EP0 IN byte count to 1
		BD0I.status = 0xC8;			// send packet as DATA1, set UOWN bit
		break;

		case GET_TICK:
		BD0I.address[0] = (tick_checkin) ? 0x01:0x00;
		tick_checkin = 0;
		BD0I.bytecount = 0x01;		// set EP0 IN byte count to 1
		BD0I.status = 0xC8;			// send packet as DATA1, set UOWN bit
		break;

		case UNKILL_CREEPA:
		killtower = USB_buffer_data[wValue];
		killvalueA = killvalueA ^ (0x0<<killtower);
		BD0I.bytecount = 0x00;
		BD0I.status = 0xC8;
		break;

		case UNKILL_CREEPB:
		killtower = USB_buffer_data[wValue];
		killvalueB = killvalueB ^ (0x0<<killtower);
		BD0I.bytecount = 0x00;
		BD0I.status = 0xC8;
		break;


	}
	/*	case 0x00:
			set_LED(0,0);
			BD0I.bytecount = 0x00;		// set EP0 IN byte count to 0
			BD0I.status = 0xC8;			// send packet as DATA1, set UOWN bit
			break;
		case 0x01:
			set_LED(0,1);
			BD0I.bytecount = 0x00;		// set EP0 IN byte count to 0
			BD0I.status = 0xC8;			// send packet as DATA1, set UOWN bit
			break;
		case 0x02:
			set_LED(0,2);
			//BD0I.address[0] = (PORTAbits.RA2) ? 0x01:0x00;	
			BD0I.bytecount = 0x01;		// set EP0 IN byte count to 1
			BD0I.status = 0xC8;			// send packet as DATA1, set UOWN bit
			break;
		case 0x03:
			set_LED(1,0);
			//DUTY = USB_buffer_data[wValue];
			BD0I.bytecount = 0x00;		// set EP0 IN byte count to 0
			BD0I.status = 0xC8;			// send packet as DATA1, set UOWN bit
			break;
		case 0x04:
			set_LED(1,1);		
			BD0I.bytecount = 0x00;		// set EP0 IN byte count to 0
			BD0I.status = 0xC8;			// send packet as DATA1, set UOWN bit
			break;
		case 0x05:
			set_LED(1,2);
			BD0I.bytecount = 0x01;		// set EP0 IN byte count to 1
			BD0I.status = 0xC8;			// send packet as DATA1, set UOWN bit
			break;
		case 0x06:
			set_LED(2,0);
			BD0I.bytecount = 0x01;		// set EP0 IN byte count to 1
			BD0I.status = 0xC8;			// send packet as DATA1, set UOWN bit
			break;
		case 0x07:
			set_LED(2,1);
			BD0I.bytecount = 0x01;		// set EP0 IN byte count to 1
			BD0I.status = 0xC8;			// send packet as DATA1, set UOWN bit
			break;
		case 0x08:
			set_LED(2,2);
			BD0I.bytecount = 0x01;		// set EP0 IN byte count to 1
			BD0I.status = 0xC8;			// send packet as DATA1, set UOWN bit
			break;
		case CLR_ALL:
			rows[0]=0b00000000;
			rows[1]=0b00000000;
			rows[2]=0b00000000;
			BD0I.bytecount = 0x01;		// set EP0 IN byte count to 1
			BD0I.status = 0xC8;			// send packet as DATA1, set UOWN bit
			break;
		default:
			USB_error_flags |= 0x01;	// set Request Error Flag
	}*/
}

void ProcessInToken(void) {
	switch (USB_USTAT&0x18) {	// extract the EP bits
		case EP0:
			switch (USB_dev_req) {
				case SET_ADDRESS:
					switch (UADDR = USB_address_pending) {
						case 0:
							USB_USWSTAT = DEFAULT_STATE;
#ifdef SHOW_ENUM_STATUS
							PORTB &= 0xE0;
							PORTBbits.RB1 = 1;
#endif
							break;
						default:
							USB_USWSTAT = ADDRESS_STATE;
#ifdef SHOW_ENUM_STATUS
							PORTB &= 0xE0;
							PORTBbits.RB2 = 1;
#endif
					}
					break;
				case GET_DESCRIPTOR:
					SendDescriptorPacket();
					break;
			}
			break;
		case EP1:
			break;
		case EP2:
			break;
	}
}

void ProcessOutToken(void) {
	switch (USB_USTAT&0x18) {	// extract the EP bits
		case EP0:
			if (USB_dev_req == TOWERTIMEARRAY) {
        	USB_dev_req = NO_REQUEST;
        	// Find the data in BD0O.address[]
			INTCONbits.GIE = 0;
				for (tower = 0; tower<USB_packet_length; tower++) {
					towertimearray[tower] = BD0O.address[tower];
			INTCONbits.GIE = 1;
				}
   			}
			BD0O.bytecount = MAX_PACKET_SIZE;
			BD0O.status = 0x88;
			BD0I.bytecount = 0x00;		// set EP0 IN byte count to 0
			BD0I.status = 0xC8;		// send packet as DATA1, set UOWN bit
			break;
		case EP1:
			break;
		case EP2:
			break;
	}
}

void SendDescriptorPacket(void) {
	unsigned char n;

	if (USB_bytes_left<MAX_PACKET_SIZE) {
		USB_dev_req = NO_REQUEST;	// sending a short packet, so clear device request
		USB_packet_length = USB_bytes_left;
		USB_bytes_left = 0x00;
	} else {
		USB_packet_length = MAX_PACKET_SIZE;
		USB_bytes_left -= MAX_PACKET_SIZE;
	}
	for (n = 0; n<USB_packet_length; n++) {
		BD0I.address[n] = *USB_desc_ptr++;
	}
	BD0I.bytecount = USB_packet_length;
	BD0I.status = ((BD0I.status^0x40)&0x40)|0x88; // toggle the DATA01 bit, clear the PIDs bits, and set the UOWN and DTS bits
}

//TYPEDEF STRUCT BITVAR{
//  UNSIGNED BIT0:0;
//  UNSIGNED BIT1:0;
//  UNSIGNED BIT2:0;
//  UNSIGNED BIT3:0;
//  UNSIGNED BIT4:0;
//  UNSIGNED BIT5:0;
//}BITVAR;


void main(void) {
	PORTA = 0b00000000;					// clear all PORTA pins 
	PORTB = 0;
	PORTC = 0;
	TRISB = 0b00001100;					// PORTBbits are outputs except for RB2 and RB3 (which are also AN8 and AN9)
	TRISC = 0;							// PortBbits are outputs
	TRISA = 0b01111111;				// set up RA0/AN0, RA1/AN1, RA2/AN2 and RA2/AN2 as inputs and set up RA3 - RA5 as outputs
	ADCON0 = 0b00000001;				// select AN0, enable A/D module
	ADCON1 = 0b00000101;				// set up RA0/AN0 and RA1/AN1 as an analog input and set up RA2..RA5 as digital I/Os
	ADCON2 = 0b00101110;				// configure A/D module result to left justified, acquisition time to 32 us, and clock period to 2.67 us
	T0CON = 0b10001000;					// initialize Timer0 to go off every 700 ms

	ADCON0 = 0b00000011;				// select AN0 and set GO_DONE bit to start A/D conversion

	PORTCbits.RC1=1;
	while (ADCON0bits.GO_DONE==1) {}	// do nothing until the A/D conversion is done
//	POT_VALUE = 60+ADRESH*60/255.0;					// move the 8 most significant bits of the result into POT_VALUE
	InitUSB();
	InitSPI();
	while (USB_USWSTAT!=CONFIG_STATE) {			// while the peripheral is not configured...
		ServiceUSB();							// ...service USB requests
	}
	PORTCbits.RC1=0;

/*
	Writesomething(chip2, GPIOB, 0xFF);			//Initialize towers at 'low'
	Delay100TCYx(45);
	Writesomething(chip2, GPIOB, 0xFF);
*/

	while (1) {
		//TEMP = TMR0L;								// Read the Timer0 register,
		//PORTAbits.RA1 = (TMR0H < POT_VALUE) ? 1:0;	// ...set RA1 high if the high byte of the Timer0 register is less than POT_VALUE, else clear RA1,...
		//if (PORTAbits.RA2==1) {						// ...and, if RA2 is high, then...
	
//look for creep checkins
		ADCON0 = 0b00000011;					// ...select AN0 and set GO_DONE bit to start A/D conversion,...
		while (ADCON0bits.GO_DONE==1) {}		// ...do nothing until the A/D conversion is done, and...
		CREEP_VALUE = ADRESH;					// ...move the 8 most significant bits of the result into CREEP_VALUE
		//}
		if (CREEP_VALUE < 0xE0 & CREEP_VALUE > 0X40){
			creep_checkin = 1;
			PORTCbits.RC0 = 1;
		}else {	PORTCbits.RC0 = 0;
			creep_checkin = 0;
		}
		if (CREEP_VALUE <0X40) {
			tick_checkin = 1;
			PORTCbits.RC1 = 1;
		}else {	PORTCbits.RC1 = 0;
		}

		// Tower AD Con 
		towerpos = 0x00;
		ADCON0 = 0b00000111;					// ...select AN1 and set GO_DONE bit to start A/D conversion,...
		while (ADCON0bits.GO_DONE==1) {}		// ...do nothing until the A/D conversion is done, and...
		if (ADRESH < 0xE0) {
		PORTCbits.RC0 = 1;
			towerpos += 0x80;
				}else {	PORTCbits.RC0 = 0;
			tick_checkin = 0;
		}
		ADCON0 = 0b00001011;					// ...select AN2 and set GO_DONE bit to start A/D conversion,...
		while (ADCON0bits.GO_DONE==1) {}		// ...do nothing until the A/D conversion is done, and...
		if (ADRESH < 0xE0) {
				PORTCbits.RC0 = 1;
//PORTCbits.RC0 = !PORTCbits.RC0;
			towerpos += 0x40;
				}else {	PORTCbits.RC0 = 0;
			tick_checkin = 0;
		}
		ADCON0 = 0b00001111;					// ...select AN3 and set GO_DONE bit to start A/D conversion,...
		while (ADCON0bits.GO_DONE==1) {}		// ...do nothing until the A/D conversion is done, and...
		if (ADRESH < 0xE0) {
			PORTCbits.RC0 = 1;
//	PORTCbits.RC0 = !PORTCbits.RC0;
			towerpos += 0x20;
				}else {	PORTCbits.RC0 = 0;
			tick_checkin = 0;
		}
		ADCON0 = 0b00010011;					// ...select AN4 and set GO_DONE bit to start A/D conversion,...
		while (ADCON0bits.GO_DONE==1) {}		// ...do nothing until the A/D conversion is done, and...
		if (ADRESH < 0xE0) {
				PORTCbits.RC0 = 1;
//PORTCbits.RC0 = !PORTCbits.RC0;
			towerpos += 0x10;
				}else {	PORTCbits.RC0 = 0;
			tick_checkin = 0;
		}
		ADCON0 = 0b00100011;					// ...select AN8 and set GO_DONE bit to start A/D conversion,...
		while (ADCON0bits.GO_DONE==1) {}		// ...do nothing until the A/D conversion is done, and...
		if (ADRESH < 0xE0) {
			PORTCbits.RC0 = 1;
//	PORTCbits.RC0 = !PORTCbits.RC0;
			towerpos += 0x08;
				}else {	PORTCbits.RC0 = 0;
			tick_checkin = 0;
		}
		ADCON0 = 0b00100111;					// ...select AN9 and set GO_DONE bit to start A/D conversion,...
		while (ADCON0bits.GO_DONE==1) {}		// ...do nothing until the A/D conversion is done, and...
		if (ADRESH < 0xE0) {
				PORTCbits.RC0 = 1;
//PORTCbits.RC0 = !PORTCbits.RC0;
			towerpos += 0x04;
				}else {	PORTCbits.RC0 = 0;
			tick_checkin = 0;
		}
		
		ServiceUSB();
		WriteSomething(chip1, GPIOB, towerpos);
		

		//KILLSERVO CONTROL
							// GPIOA and GPIOB on chip 2 are kill creeps.
		WriteSomething(chip2, GPIOA, ~killvalueA); // Output on SPI pin
		WriteSomething(chip2, GPIOB, ~killvalueB); // Output on SPI pin
		Delay100TCYx(115);
		WriteSomething(chip2, GPIOA, 0x00);
		WriteSomething(chip2, GPIOB, 0x00);

		WriteSomething(chip2, GPIOA, killvalueA);
		WriteSomething(chip2, GPIOB, killvalueB);
		Delay100TCYx(55);
		WriteSomething(chip2, GPIOA, 0x00);
		WriteSomething(chip2, GPIOB, 0x00);
/*
		PORTAbits.RA4 = 1;							// Uses the slider to move a single servo
		Delay100TCYx( SERVO_PLACEMENT);
		PORTAbits.RA4 = 0;
*/


		//TOWER CONTROL
							// GPIOB on chip 1 is tower servo control
							// GPIOA on chip 1 is tower LED control?
		firing = 0xFF;
		//WriteSomething (chip1, GPIOB, firing);		// Writes the byte of towers that are firing
		spi_tower = 0x01;							// iterates through the towers and delays for their particular time
		for(tower = 0; tower<8; tower++) {
		ServiceUSB();								// update to be sure to get the right value
		WriteSomething (chip1, GPIOA, spi_tower);
		Delay100TCYx(towertimearray[tower]);
		WriteSomething (chip1, GPIOA, 0);
		spi_tower = spi_tower * 2;
		}


		/*
		if (ADRESH>0b01100000 && ADRESH<0b10100000){
		//servo tower
			SERVO_PLACEMENT=SERVO_PLACEMENT+1;
			if (SERVO_PLACEMENT>135){
				SERVO_PLACEMENT=25;
				PORTAbits.RA2 = !PORTAbits.RA2;	
				}
		//PORTAbits.RA2 = !PORTAbits.RA2;
		}else if (ADRESH>0b10100000 && ADRESH<0b11100000){
			//Motor Tower
			
			PORTAbits.RA2=1;
			//PORTAbits.RA3=1;
			if (chargecycle!=0){
				Delay10KTCYx(chargecycle);
			}
			//PORTAbits.RA3=0;
			chargecycle = chargecycle+deltacharge;
			if ((chargecycle<=0 )|| (chargecycle>255)){
				
				PORTAbits.RA4=!PORTAbits.RA4;
				deltacharge=9-deltacharge;
				if (deltacharge>0){
				chargecycle=0;
				}else{
				chargecycle=0b11111111;
				}
				chargecycle=chargecycle+deltacharge;
			}
			PORTAbits.RA2=0;
		}	
		*/
		
/*		AD CONVERTER
		
		if (checkfortowers == 1) { 		
		for (adport = 0; adport < 8; adport++){
															//	tower  0 1 2 3 4 5 67 needs to be plugged in to
		pollbyte = 10001111	& (adport << 4);	//1xxx1111			CH 0 2 4 6 1 3 5 7
		RequestAByte(pollbyte);					//poll CH0
		if (AD_data > 0x80) {
		AD_array[adport] = 1;
		}else {AD_array[adport] = 0;
		}
		}
		towerchange = 1;
		checkfortowers = 0;
		}


		if (towerchange == 1){
		for (adport = 0; adport < 8; adport++){
		adport = 0b000;										//	tower  0 1 2 3 4 5 6 7 needs to be plugged in to
		pollbyte = 10001111	& (adport << 4);	//1xxx1111			CH 0 2 4 6 1 3 5 7
		RequestAByte(pollbyte);					//poll CH0
		AD_type_array[adport] = AD_data;
		towerchange = 0;
		}
		}

*/


/*		while (INTCONbits.T0IF==0) {} // use these two lines or the delay10KTCYx(6) line
		INTCONbits.T0IF = 0;	
*/
		
		
		//Delay10KTCYx(6); //using this delay method instead of the timer also works
	}
}